using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Universal.Domain.Entities;
using Universal.Domain.Repositories;
using Universal.Infrastructure.DB;

namespace Universal.Infrastructure.Repositories;

/// <summary>
/// 通用仓储接口实现类
/// </summary>
public class EfRepository<T> : IRepository<T> where T : EntityBase
{
    private readonly AppDbContext _db;
    private readonly DbSet<T> _tb;
    public EfRepository(AppDbContext db)
    {
        _db = db;
        _tb = db.Set<T>();
    }

    public async Task<T> AddAsync(T entity)
    {
        var obj = (await _tb.AddAsync(entity)).Entity;
        await _db.SaveChangesAsync();
        return obj;
    }

    public async Task DeleteAsync(T entity)
    {
        _tb.Remove(entity);
        await _db.SaveChangesAsync();
    }

    //AsNoTracking() 不跟踪查询结果，提高查询性能
    public async Task<IEnumerable<T>> GetAllAsync()
    {
        var list = await _tb.AsNoTracking().ToListAsync();
        return list;
    }

    public async Task<T?> GetByIdAsync(Guid id)
    {
        var obj = await _tb.FindAsync(id);
        return obj;
    }

    public async Task<T?> GetByIdWithIncludesAsync(Guid id, params Expression<Func<T, object>>[] includes)
    {
        IQueryable<T> query = _tb;
        foreach (var include in includes)
        {
            query = query.Include(include);
        }
        return await query.FirstOrDefaultAsync(e => e.Id == id);
    }

    /// <summary>
    /// 分页查询
    /// </summary>
    /// <param name="pageIndex">页码</param>
    /// <param name="pageSize">每页条数</param>
    /// <param name="includes">包含的导航属性</param>
    /// <returns>分页数据</returns>
    public async Task<(IEnumerable<T> Items, int TotalCount)> GetPagedAsync(int pageIndex, int pageSize, params Expression<Func<T, object>>[] includes)
    {
        IQueryable<T> query = _tb.AsNoTracking();
        foreach (var include in includes)
        {
            query = query.Include(include);
        }
        var total = await query.CountAsync();
        var items = await query.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
        return (items, total);
    }

    /// <summary>
    /// 模糊查询
    /// </summary>
    /// <param name="keyword">关键字</param>
    /// <returns>查询结果</returns>
    public IQueryable<T> Query()
    {
        return _tb;
    }

    public async Task UpdateAsync(T entity)
    {
        _tb.Update(entity);
        await _db.SaveChangesAsync();
    }
}